package com.chinaoct.siku.util;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;




public class SimplProxyUtil {
	
	private static Logger logger = LoggerFactory.getLogger(SimplProxyUtil.class);

	
	public static Map<String, Object> postByClient(ServletRequest request, ServletResponse response, String targetUrl,
			byte[] requestBody) throws Exception {
		Map<String, Object> map = getPostClient(request, response, targetUrl, requestBody);
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		String contentType = httpRequest.getHeader("content-type");
		if (null != map && "-1".equals(map.get("status").toString())) {
			String reault = map.get("result").toString();
			if (reault.indexOf("Connection timed out") >= 0) {
				map = getPostClient(request, response, targetUrl, requestBody);
			}
		}
		if (null != map && "-1".equals(map.get("status").toString())) {
			throw new Exception(map.get("result").toString());
		}
		response.setCharacterEncoding("UTF-8");
		response.setContentType(contentType);
		PrintWriter out;
		out = response.getWriter();
		out.print(map.get("result"));
		out.flush();
		return map;
	}

	public static Map<String, Object> getPostClient(ServletRequest request, ServletResponse response, String targetUrl,
			byte[] requestBody) {
		CloseableHttpClient closeableHttpClient =HttpRequest.getHttpClient();
		HttpPost httppost = new HttpPost(targetUrl);
		
		try {
			HttpServletRequest httpRequest = (HttpServletRequest) request;
			String contentType = httpRequest.getHeader("content-type");
			httppost.addHeader("content-type", contentType);
			Enumeration enums = httpRequest.getHeaderNames();
			boolean hasAccept=false;
			if(!hasAccept) {
				httppost.addHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;");
			}
			RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(120000).setSocketTimeout(120000)
					.setConnectionRequestTimeout(120000).build();
			httppost.setConfig(requestConfig);
			StringEntity entity = new StringEntity(new String(requestBody), "utf-8");
			httppost.setEntity(entity);
			HttpResponse httpResponse = closeableHttpClient.execute(httppost);
			int code = httpResponse.getStatusLine().getStatusCode();
			String page = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("status", code);
			map.put("result", page);
			return map;
		} catch (Exception e) {
			e.printStackTrace();
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("status", -1);
			map.put("result", e.getMessage());
			return map;
		} finally {
			if (null != httppost)
				httppost.releaseConnection();
		}
	}
	
	/**
	 * 使用GET提交到目标服务器。
	 * 
	 * @param request`
	 * @param targetUrl
	 * @throws IOException
	 */
	public static Map<String, Object> get(ServletRequest request,  String targetUrl)
			throws IOException {
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		String contentType = httpRequest.getHeader("content-type");
		targetUrl = appendParams(httpRequest, targetUrl);

		if (targetUrl.startsWith("https")) {
			return getssl(contentType, targetUrl);
		}
		CloseableHttpClient client = HttpRequest.getHttpClient();
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();// 设置请求和传输超时时间
		HttpGet httpGet = new HttpGet(targetUrl);
		httpGet.setConfig(requestConfig);
		httpGet.setHeader("content-type", "application/json;charset=UTF-8");
		httpGet.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;");
		int code;
		String result;
		try {
			HttpResponse responseByproxy = client.execute(httpGet);
			code = responseByproxy.getStatusLine().getStatusCode();
			result = EntityUtils.toString(responseByproxy.getEntity(), "utf-8");
		} finally {
			if (null != httpGet)
				httpGet.releaseConnection();
			client = null;
			requestConfig = null;
		}

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("status", code);
		map.put("result", result);
		return map;
		// in.close();
	}

	private static Map<String, Object> getssl(String contentType,  String targetUrl) throws IOException {

		CloseableHttpClient httpClient = createSSLClientDefault();
		CloseableHttpResponse responseByproxy = null;
		HttpGet get = new HttpGet(targetUrl);
		String result = "";
		int code = 0;
		try {
			responseByproxy = httpClient.execute(get);
			code = responseByproxy.getStatusLine().getStatusCode();
			HttpEntity entity = responseByproxy.getEntity();
			if (null != entity) {
				result = EntityUtils.toString(entity, "UTF-8");
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage(),ex);
		} finally {
			if (null != responseByproxy) {
				try {
					EntityUtils.consume(responseByproxy.getEntity());
					get.releaseConnection();
				} catch (IOException ex) {
					logger.error(ex.getMessage(),ex);
				}
			}
		}

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("status", code);
		map.put("result", result);
		return map;
	}

	public static String appendParams(HttpServletRequest request, String url) {
		Map map = new HashMap();
		Enumeration paramNames = request.getParameterNames();
		while (paramNames.hasMoreElements()) {
			String paramName = (String) paramNames.nextElement();

			String[] paramValues = request.getParameterValues(paramName);
			if (paramValues.length == 1) {
				String paramValue = paramValues[0];
				if (paramValue.length() != 0) {
					map.put(paramName, paramValue);
				}
			}
		}

		Set<Map.Entry<String, String>> set = map.entrySet();
		if (url.indexOf("?") <= 0) {
			url += "?param1=1";
		}
		for (Map.Entry entry : set) {
			if ("path".equals(entry.getKey()) || "_".equals(entry.getKey())) {
				continue;
			}

			try {
				String value = URLEncoder.encode(entry.getValue().toString(), "UTF-8");
				url += "&" + entry.getKey() + "=" + value;

			} catch (UnsupportedEncodingException e) {
				System.out.println(e.getMessage());
				url += "&" + entry.getKey() + "=" + entry.getValue();
			}
		}
		return url;
	}
	
	private static CloseableHttpClient createSSLClientDefault() {
		SSLContext sslContext;
		try {
			sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				// 信任所有
				@Override
				public boolean isTrusted(X509Certificate[] xcs, String string) {
					return true;
				}
			}).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
			return HttpClients.custom().setSSLSocketFactory(sslsf).build();
		} catch (Exception ex) {
			logger.error(ex.getMessage(),ex);
		}
		return HttpClients.createDefault();
	}

}
